/*
 * state.c
 *
 *  Created on: May 21, 2012
 *      Author: root
 */
#include "unp.h"
#include "ftp_client.h"

void state_I_REPLY(USER_CMD cmd_info) {
	//printf("I_REPLY\n");
	printf("Password: ");
	fflush(stdout);

	Fgets(cmd_info.arg1, MAXLINE, stdin);
	parse_LF(cmd_info.arg1);

	send_request(cmd_info.sockfd, "PASS", cmd_info.arg1);

}

void state_S_REPLY(USER_CMD cmd_info) {
	//printf("S_REPLY\n");
	char res_num[10];

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);
	sscanf(response, "%s ", res_num);

	if (!strcmp(res_num, "230")) {
		log_bit = 1;

		Fputs(response, stdout);
		memset(response, 0, strlen(response));

		send_request(cmd_info.sockfd, "SYST", "");
		print_response(cmd_info.sockfd);

	} else if (res_num[0] == '2') //success
			{
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
	} else if (!strcmp(res_num, "421")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		connect_bit = 0;
		log_bit = 0;
		close(cmd_info.sockfd);
		state = U_CMD;

	} else { //failure, error
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
	}

}

int state_S_REPLY1(USER_CMD cmd_info) {
	//printf("S_REPLY1\n");
	char res_num[10];

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);

	sscanf(response, "%s ", res_num);
	if (!strcmp(res_num, "200")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));

		if (passive_bit == 0) {

			send_request(cmd_info.sockfd, "PORT", PORT_arg);
		} else if (passive_bit == 1) {

			send_request(cmd_info.sockfd, "PASV", "");
		}

		return (S_REPLY2);
	} else if (!strcmp(res_num, "421")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		connect_bit = 0;
		log_bit = 0;
		close(cmd_info.sockfd);
		return(U_CMD);

	} else {
		fputs(response, stdout);
		memset(response, 0, strlen(response));
		return (U_CMD);
	}
}

USER_CMD state_S_REPLY2(USER_CMD cmd_info) {
	//printf("S_REPLY2\n");

	char w1[20], w2[20], w3[20], w4[40];
	char res_num[10];
	char *token;

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);

	sscanf(response, "%s %s %s %s %s", res_num, w1, w2, w3, w4);

	if (!strcmp(res_num, "421")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		connect_bit = 0;
		log_bit = 0;
		close(cmd_info.sockfd);
		state = U_CMD;

	}

	if (!strcmp(res_num, "227")) { //passive

		char addr[100];

		Fputs(response, stdout);
		memset(response, 0, strlen(response));


		char port1_c[10], port2_c[10];
		int port1_i, port2_i;
		int port;
		char data_port[10];

		token = strtok(w4, ",");
		token = strtok(NULL, ",");
		token = strtok(NULL, ",");
		token = strtok(NULL, ",");
		token = strtok(NULL, ",");
		strcpy(port1_c, token);
		token = strtok(NULL, ",");
		strcpy(port2_c, token);

		port1_i = atoi(port1_c);
		port2_i = atoi(port2_c);


		port = port1_i * 256 + port2_i;

		sprintf(data_port, "%d", port);

		sprintf(addr, "%s\n", token);

		if (!strcmp(cmd_info.cmd, "nlist")) {
			send_request(cmd_info.sockfd, "NLST", "");
		} else if (!strcmp(cmd_info.cmd, "ls")
				|| !strcmp(cmd_info.cmd, "dir")) {
			send_request(cmd_info.sockfd, "LIST", "");
		} else if (!strcmp(cmd_info.cmd, "get")) {
			send_request(cmd_info.sockfd, "RETR", cmd_info.arg1);
		} else if (!strcmp(cmd_info.cmd, "put")) {
			send_request(cmd_info.sockfd, "STOR", cmd_info.arg2);
		}

		file_sockfd = tcp_connect(ftp_serv_ip, data_port);

		state = P_REPLY;
		return (cmd_info);

	} else if (!strcmp(res_num, "200")) { //active

		Fputs(response, stdout);
		memset(response, 0, strlen(response));

		if (!strcmp(cmd_info.cmd, "nlist")) {
			send_request(cmd_info.sockfd, "NLST", "");
		} else if (!strcmp(cmd_info.cmd, "ls")
				|| !strcmp(cmd_info.cmd, "dir")) {
			send_request(cmd_info.sockfd, "LIST", "");
		} else if (!strcmp(cmd_info.cmd, "get")) {
			send_request(cmd_info.sockfd, "RETR", cmd_info.arg1);
		} else if (!strcmp(cmd_info.cmd, "put")) {
			send_request(cmd_info.sockfd, "STOR", cmd_info.arg2);
		}

		state = P_REPLY;
		return (cmd_info);
	} else {

		fputs(response, stdout);
		memset(response, 0, strlen(response));
		state = U_CMD;
		return (cmd_info);

	}
}

void state_S_REPLY3(USER_CMD cmd_info) {
	//printf("S_REPLY3\n");
	char res_num[10];

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);

	sscanf(response, "%s ", res_num);

	if (!strcmp(res_num, "221")) {
		if (!strcmp(cmd_info.cmd, "close")) {
			Fputs(response, stdout);
			memset(response, 0, strlen(response));
			close(cmd_info.sockfd);
			state = U_CMD;
		} else if (!strcmp(cmd_info.cmd, "quit")||!strcmp(cmd_info.cmd,"bye")) {
			Fputs(response, stdout);
			memset(response, 0, strlen(response));
			exit(0);
		}
	} else if (!strcmp(res_num, "421")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		connect_bit = 0;
		log_bit = 0;
		close(cmd_info.sockfd);
		state = U_CMD;

	}
}

USER_CMD state_P_REPLY(USER_CMD cmd_info) {
	//printf("P_REPLY\n");

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);

	sscanf(response, "%s ", res_num);

	if (!strcmp(res_num, "150")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));

		if (passive_bit == 0) {

			cliaddr = Malloc(addrlen);
			len = addrlen;
			file_sockfd = accept(listenfd, cliaddr, &len);
		}
		state = DATA;

	} else if (!strcmp(res_num, "553")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		state = U_CMD;

	} else if (!strcmp(res_num, "421")) {
		Fputs(response, stdout);
		memset(response, 0, strlen(response));
		connect_bit = 0;
		log_bit = 0;
		close(cmd_info.sockfd);
		state = U_CMD;

	} else {
		Fputs(response, stdout);
		state = U_CMD;
	}
	return (cmd_info);
}

USER_CMD state_DATA(USER_CMD cmd_info) {
	//printf("DATA\n");
	char data_buf[MAXLINE];

	int data_len;
	int length = 0;


	if (!strcmp(cmd_info.cmd, "ls") || !strcmp(cmd_info.cmd, "dir")
			|| !strcmp(cmd_info.cmd, "nlist")) {
		while ((data_len = readline(file_sockfd, data_buf, MAXLINE)) > 0) {
			Fputs(data_buf, stdout);
		}
		memset(data_buf, 0, strlen(data_buf));
	}

	if (!strcmp(cmd_info.cmd, "get")) {

		FILE *fp = fopen(cmd_info.arg2, "w");

		while ((data_len = readline(file_sockfd, data_buf, MAXLINE)) > 0) {
			fwrite(data_buf, 1, data_len, fp);

			length = length + data_len;
		}
		printf("%d bytes received in \n", length);

		memset(data_buf, 0, data_len);
		fclose(fp);

	}

	if (!strcmp(cmd_info.cmd, "put")) {

		int fd;
		fd = open(cmd_info.arg1, O_RDONLY);

		while ((data_len = readline(fd, data_buf, MAXLINE)) > 0) {
			Writen(file_sockfd, data_buf, data_len);

			length = length + data_len;
		}
		printf("%d bytes sent in \n", length);
		memset(data_buf, 0, data_len);
		close(fd);

		data_len = 0;

	}

	length = 0;

	memset(response, 0, strlen(response));

	close(file_sockfd);

	if ((n = readBuf(rbuf, cmd_info.sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);

	Fputs(response, stdout);
	memset(response, 0, strlen(response));
	state = U_CMD;
	return (cmd_info);
}

void print_response(int sockfd) {
	if ((n = readBuf(rbuf, sockfd)) < 0)
		err_sys("read error");
	getCRLF(rbuf, response, MAXLINE);
	fputs(response, stdout);
	memset(response, 0, strlen(response));
}

